| Conditions | 19 |
| Paths | > 20000 |
| Total Lines | 634 |
| Code Lines | 289 |
| Lines | 0 |
| Ratio | 0 % |
| Changes | 0 | ||
Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.
For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.
Commonly applied refactorings include:
If many parameters/temporary variables are present:
Complex classes like webpack.config.js ➔ ??? often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
| 1 | |||
| 45 | module.exports = (webpackEnv) => { |
||
| 46 | const isEnvDevelopment = webpackEnv === 'development'; |
||
| 47 | const isEnvProduction = webpackEnv === 'production'; |
||
| 48 | |||
| 49 | // Webpack uses `publicPath` to determine where the app is being served from. |
||
| 50 | // It requires a trailing slash, or the file assets will get an incorrect path. |
||
| 51 | // In development, we always serve from the root. This makes config easier. |
||
| 52 | const publicPath = isEnvProduction |
||
| 53 | ? paths.servedPath |
||
| 54 | : isEnvDevelopment && '/'; |
||
| 55 | |||
| 56 | // Some apps do not use client-side routing with pushState. |
||
| 57 | // For these, "homepage" can be set to "." to enable relative asset paths. |
||
| 58 | const shouldUseRelativeAssetPaths = publicPath === './'; |
||
| 59 | |||
| 60 | // `publicUrl` is just like `publicPath`, but we will provide it to our app |
||
| 61 | // as %PUBLIC_URL% in `index.html` and `process.env.PUBLIC_URL` in JavaScript. |
||
| 62 | // Omit trailing slash as %PUBLIC_URL%/xyz looks better than %PUBLIC_URL%xyz. |
||
| 63 | const publicUrl = isEnvProduction |
||
| 64 | ? publicPath.slice(0, -1) |
||
| 65 | : isEnvDevelopment && ''; |
||
| 66 | |||
| 67 | // Get environment variables to inject into our app. |
||
| 68 | const env = getClientEnvironment(publicUrl); |
||
| 69 | |||
| 70 | // common function to get style loaders |
||
| 71 | const getStyleLoaders = (cssOptions, preProcessor) => { |
||
| 72 | const loaders = [ |
||
| 73 | isEnvDevelopment && require.resolve('style-loader'), |
||
| 74 | isEnvProduction && { |
||
| 75 | loader: MiniCssExtractPlugin.loader, |
||
| 76 | options: Object.assign( |
||
| 77 | {}, |
||
| 78 | shouldUseRelativeAssetPaths ? { publicPath: '../../' } : undefined |
||
| 79 | ), |
||
| 80 | }, |
||
| 81 | { |
||
| 82 | loader: require.resolve('css-loader'), |
||
| 83 | options: cssOptions, |
||
| 84 | }, |
||
| 85 | { |
||
| 86 | |||
| 87 | // Options for PostCSS as we reference these options twice |
||
| 88 | // Adds vendor prefixing based on your specified browser support in |
||
| 89 | // package.json |
||
| 90 | loader: require.resolve('postcss-loader'), |
||
| 91 | options: { |
||
| 92 | |||
| 93 | // Necessary for external CSS imports to work |
||
| 94 | // https://github.com/facebook/create-react-app/issues/2677 |
||
| 95 | ident: 'postcss', |
||
| 96 | plugins: () => [ |
||
| 97 | require('postcss-flexbugs-fixes'), |
||
| 98 | require('postcss-preset-env')({ |
||
| 99 | autoprefixer: { |
||
| 100 | flexbox: 'no-2009', |
||
| 101 | }, |
||
| 102 | stage: 3, |
||
| 103 | }), |
||
| 104 | ], |
||
| 105 | sourceMap: isEnvProduction && shouldUseSourceMap, |
||
| 106 | }, |
||
| 107 | }, |
||
| 108 | ].filter(Boolean); |
||
| 109 | |||
| 110 | if (preProcessor) { |
||
| 111 | loaders.push({ |
||
| 112 | loader: require.resolve(preProcessor), |
||
| 113 | options: { |
||
| 114 | sourceMap: isEnvProduction && shouldUseSourceMap, |
||
| 115 | }, |
||
| 116 | }); |
||
| 117 | } |
||
| 118 | |||
| 119 | return loaders; |
||
| 120 | }; |
||
| 121 | |||
| 122 | return { |
||
| 123 | mode: isEnvProduction ? 'production' : isEnvDevelopment && 'development', |
||
| 124 | |||
| 125 | // Stop compilation early in production |
||
| 126 | bail: isEnvProduction, |
||
| 127 | devtool: isEnvProduction |
||
| 128 | ? shouldUseSourceMap |
||
| 129 | ? 'source-map' |
||
| 130 | : false |
||
| 131 | : isEnvDevelopment && 'cheap-module-source-map', |
||
| 132 | |||
| 133 | // These are the "entry points" to our application. |
||
| 134 | // This means they will be the "root" imports that are included in JS bundle. |
||
| 135 | entry: [ |
||
| 136 | |||
| 137 | // Include an alternative client for WebpackDevServer. A client's job is to |
||
| 138 | // connect to WebpackDevServer by a socket and get notified about changes. |
||
| 139 | // When you save a file, the client will either apply hot updates (in case |
||
| 140 | // of CSS changes), or refresh the page (in case of JS changes). When you |
||
| 141 | // make a syntax error, this client will display a syntax error overlay. |
||
| 142 | // Note: instead of the default WebpackDevServer client, we use a custom one |
||
| 143 | // to bring better experience for Create React App users. You can replace |
||
| 144 | // the line below with these two lines if you prefer the stock client: |
||
| 145 | // require.resolve('webpack-dev-server/client') + '?/', |
||
| 146 | // require.resolve('webpack/hot/dev-server'), |
||
| 147 | isEnvDevelopment && |
||
| 148 | require.resolve('react-dev-utils/webpackHotDevClient'), |
||
| 149 | |||
| 150 | // Finally, this is your app's code: |
||
| 151 | paths.appIndexJs, |
||
| 152 | |||
| 153 | // We include the app code last so that if there is a runtime error during |
||
| 154 | // initialization, it doesn't blow up the WebpackDevServer client, and |
||
| 155 | // changing JS code would still trigger a refresh. |
||
| 156 | ].filter(Boolean), |
||
| 157 | output: { |
||
| 158 | |||
| 159 | // The build folder. |
||
| 160 | path: isEnvProduction ? paths.appBuild : undefined, |
||
| 161 | |||
| 162 | // Add /* filename */ comments to generated require()s in the output. |
||
| 163 | pathinfo: isEnvDevelopment, |
||
| 164 | |||
| 165 | // There will be one main bundle, and one file per asynchronous chunk. |
||
| 166 | // In development, it does not produce real files. |
||
| 167 | filename: isEnvProduction |
||
| 168 | ? 'static/js/[name].[chunkhash:8].js' |
||
| 169 | : isEnvDevelopment && 'static/js/bundle.js', |
||
| 170 | |||
| 171 | // There are also additional JS chunk files if you use code splitting. |
||
| 172 | chunkFilename: isEnvProduction |
||
| 173 | ? 'static/js/[name].[chunkhash:8].chunk.js' |
||
| 174 | : isEnvDevelopment && 'static/js/[name].chunk.js', |
||
| 175 | |||
| 176 | // We inferred the "public path" (such as / or /my-project) from homepage. |
||
| 177 | // We use "/" in development. |
||
| 178 | publicPath, |
||
| 179 | |||
| 180 | // Point sourcemap entries to original disk location (format as URL on Windows) |
||
| 181 | devtoolModuleFilenameTemplate: isEnvProduction |
||
| 182 | ? (info) => |
||
| 183 | path |
||
| 184 | .relative(paths.appSrc, info.absoluteResourcePath) |
||
| 185 | .replace(/\\/g, '/') |
||
| 186 | : isEnvDevelopment && |
||
| 187 | ((info) => path.resolve(info.absoluteResourcePath).replace(/\\/g, '/')), |
||
| 188 | }, |
||
| 189 | optimization: { |
||
| 190 | minimize: isEnvProduction, |
||
| 191 | minimizer: [ |
||
| 192 | |||
| 193 | // This is only used in production mode |
||
| 194 | new TerserPlugin({ |
||
| 195 | terserOptions: { |
||
| 196 | parse: { |
||
| 197 | |||
| 198 | // we want terser to parse ecma 8 code. However, we don't want it |
||
| 199 | // to apply any minfication steps that turns valid ecma 5 code |
||
| 200 | // into invalid ecma 5 code. This is why the 'compress' and 'output' |
||
| 201 | // sections only apply transformations that are ecma 5 safe |
||
| 202 | // https://github.com/facebook/create-react-app/pull/4234 |
||
| 203 | ecma: 8, |
||
| 204 | }, |
||
| 205 | compress: { |
||
| 206 | ecma: 5, |
||
| 207 | warnings: false, |
||
| 208 | |||
| 209 | // Disabled because of an issue with Uglify breaking seemingly valid code: |
||
| 210 | // https://github.com/facebook/create-react-app/issues/2376 |
||
| 211 | // Pending further investigation: |
||
| 212 | // https://github.com/mishoo/UglifyJS2/issues/2011 |
||
| 213 | comparisons: false, |
||
| 214 | |||
| 215 | // Disabled because of an issue with Terser breaking valid code: |
||
| 216 | // https://github.com/facebook/create-react-app/issues/5250 |
||
| 217 | // Pending futher investigation: |
||
| 218 | // https://github.com/terser-js/terser/issues/120 |
||
| 219 | inline: 2, |
||
| 220 | }, |
||
| 221 | mangle: { |
||
| 222 | safari10: true, |
||
| 223 | }, |
||
| 224 | output: { |
||
| 225 | ecma: 5, |
||
| 226 | comments: false, |
||
| 227 | |||
| 228 | // Turned on because emoji and regex is not minified properly using default |
||
| 229 | // https://github.com/facebook/create-react-app/issues/2488 |
||
| 230 | ascii_only: true, |
||
| 231 | }, |
||
| 232 | }, |
||
| 233 | |||
| 234 | // Use multi-process parallel running to improve the build speed |
||
| 235 | // Default number of concurrent runs: os.cpus().length - 1 |
||
| 236 | parallel: true, |
||
| 237 | |||
| 238 | // Enable file caching |
||
| 239 | cache: true, |
||
| 240 | sourceMap: shouldUseSourceMap, |
||
| 241 | }), |
||
| 242 | |||
| 243 | // This is only used in production mode |
||
| 244 | new OptimizeCSSAssetsPlugin({ |
||
| 245 | cssProcessorOptions: { |
||
| 246 | parser: safePostCssParser, |
||
| 247 | map: shouldUseSourceMap |
||
| 248 | ? { |
||
| 249 | |||
| 250 | // `inline: false` forces the sourcemap to be output into a |
||
| 251 | // separate file |
||
| 252 | inline: false, |
||
| 253 | |||
| 254 | // `annotation: true` appends the sourceMappingURL to the end of |
||
| 255 | // the css file, helping the browser find the sourcemap |
||
| 256 | annotation: true, |
||
| 257 | } |
||
| 258 | : false, |
||
| 259 | }, |
||
| 260 | }), |
||
| 261 | ], |
||
| 262 | |||
| 263 | // Automatically split vendor and commons |
||
| 264 | // https://twitter.com/wSokra/status/969633336732905474 |
||
| 265 | // https://medium.com/webpack/webpack-4-code-splitting-chunk-graph-and-the-splitchunks-optimization-be739a861366 |
||
| 266 | splitChunks: { |
||
| 267 | chunks: 'all', |
||
| 268 | name: false, |
||
| 269 | }, |
||
| 270 | |||
| 271 | // Keep the runtime chunk separated to enable long term caching |
||
| 272 | // https://twitter.com/wSokra/status/969679223278505985 |
||
| 273 | runtimeChunk: true, |
||
| 274 | }, |
||
| 275 | resolve: { |
||
| 276 | |||
| 277 | // This allows you to set a fallback for where Webpack should look for modules. |
||
| 278 | // We placed these paths second because we want `node_modules` to "win" |
||
| 279 | // if there are any conflicts. This matches Node resolution mechanism. |
||
| 280 | // https://github.com/facebook/create-react-app/issues/253 |
||
| 281 | modules: [ 'node_modules' ].concat( |
||
| 282 | |||
| 283 | // It is guaranteed to exist because we tweak it in `env.js` |
||
| 284 | process.env.NODE_PATH.split(path.delimiter).filter(Boolean) |
||
| 285 | ), |
||
| 286 | |||
| 287 | // These are the reasonable defaults supported by the Node ecosystem. |
||
| 288 | // We also include JSX as a common component filename extension to support |
||
| 289 | // some tools, although we do not recommend using it, see: |
||
| 290 | // https://github.com/facebook/create-react-app/issues/290 |
||
| 291 | // `web` extension prefixes have been added for better support |
||
| 292 | // for React Native Web. |
||
| 293 | extensions: paths.moduleFileExtensions |
||
| 294 | .map((ext) => `.${ext}`) |
||
| 295 | .filter((ext) => useTypeScript || !ext.includes('ts')), |
||
| 296 | alias: { |
||
| 297 | |||
| 298 | // Support React Native Web |
||
| 299 | // https://www.smashingmagazine.com/2016/08/a-glimpse-into-the-future-with-react-native-for-web/ |
||
| 300 | 'react-native': 'react-native-web', |
||
| 301 | }, |
||
| 302 | plugins: [ |
||
| 303 | |||
| 304 | // Adds support for installing with Plug'n'Play, leading to faster installs and adding |
||
| 305 | // guards against forgotten dependencies and such. |
||
| 306 | PnpWebpackPlugin, |
||
| 307 | |||
| 308 | // Prevents users from importing files from outside of src/ (or node_modules/). |
||
| 309 | // This often causes confusion because we only process files within src/ with babel. |
||
| 310 | // To fix this, we prevent you from importing files out of src/ -- if you'd like to, |
||
| 311 | // please link the files into your node_modules/ and let module-resolution kick in. |
||
| 312 | // Make sure your source files are compiled, as they will not be processed in any way. |
||
| 313 | new ModuleScopePlugin(paths.appSrc, [ paths.appPackageJson ]), |
||
| 314 | ], |
||
| 315 | }, |
||
| 316 | resolveLoader: { |
||
| 317 | plugins: [ |
||
| 318 | |||
| 319 | // Also related to Plug'n'Play, but this time it tells Webpack to load its loaders |
||
| 320 | // from the current package. |
||
| 321 | PnpWebpackPlugin.moduleLoader(module), |
||
| 322 | ], |
||
| 323 | }, |
||
| 324 | module: { |
||
| 325 | strictExportPresence: true, |
||
| 326 | rules: [ |
||
| 327 | |||
| 328 | // Disable require.ensure as it's not a standard language feature. |
||
| 329 | { parser: { requireEnsure: false } }, |
||
| 330 | |||
| 331 | // First, run the linter. |
||
| 332 | // It's important to do this before Babel processes the JS. |
||
| 333 | { |
||
| 334 | test: /\.(js|mjs|jsx)$/, |
||
| 335 | enforce: 'pre', |
||
| 336 | use: [ |
||
| 337 | { |
||
| 338 | options: { |
||
| 339 | formatter: require.resolve('react-dev-utils/eslintFormatter'), |
||
| 340 | eslintPath: require.resolve('eslint'), |
||
| 341 | |||
| 342 | }, |
||
| 343 | loader: require.resolve('eslint-loader'), |
||
| 344 | }, |
||
| 345 | ], |
||
| 346 | include: paths.appSrc, |
||
| 347 | }, |
||
| 348 | { |
||
| 349 | |||
| 350 | // "oneOf" will traverse all following loaders until one will |
||
| 351 | // match the requirements. When no loader matches it will fall |
||
| 352 | // back to the "file" loader at the end of the loader list. |
||
| 353 | oneOf: [ |
||
| 354 | |||
| 355 | // "url" loader works like "file" loader except that it embeds assets |
||
| 356 | // smaller than specified limit in bytes as data URLs to avoid requests. |
||
| 357 | // A missing `test` is equivalent to a match. |
||
| 358 | { |
||
| 359 | test: [ /\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/ ], |
||
| 360 | loader: require.resolve('url-loader'), |
||
| 361 | options: { |
||
| 362 | limit: 10000, |
||
| 363 | name: 'static/media/[name].[hash:8].[ext]', |
||
| 364 | }, |
||
| 365 | }, |
||
| 366 | |||
| 367 | // Process application JS with Babel. |
||
| 368 | // The preset includes JSX, Flow, TypeScript, and some ESnext features. |
||
| 369 | { |
||
| 370 | test: /\.(js|mjs|jsx|ts|tsx)$/, |
||
| 371 | include: paths.appSrc, |
||
| 372 | loader: require.resolve('babel-loader'), |
||
| 373 | options: { |
||
| 374 | customize: require.resolve( |
||
| 375 | 'babel-preset-react-app/webpack-overrides' |
||
| 376 | ), |
||
| 377 | |||
| 378 | plugins: [ |
||
| 379 | [ |
||
| 380 | require.resolve('babel-plugin-named-asset-import'), |
||
| 381 | { |
||
| 382 | loaderMap: { |
||
| 383 | svg: { |
||
| 384 | ReactComponent: |
||
| 385 | '@svgr/webpack?-prettier,-svgo![path]', |
||
| 386 | }, |
||
| 387 | }, |
||
| 388 | }, |
||
| 389 | ], |
||
| 390 | ], |
||
| 391 | |||
| 392 | // This is a feature of `babel-loader` for webpack (not Babel itself). |
||
| 393 | // It enables caching results in ./node_modules/.cache/babel-loader/ |
||
| 394 | // directory for faster rebuilds. |
||
| 395 | cacheDirectory: true, |
||
| 396 | cacheCompression: isEnvProduction, |
||
| 397 | compact: isEnvProduction, |
||
| 398 | }, |
||
| 399 | }, |
||
| 400 | |||
| 401 | // Process any JS outside of the app with Babel. |
||
| 402 | // Unlike the application JS, we only compile the standard ES features. |
||
| 403 | { |
||
| 404 | test: /\.(js|mjs)$/, |
||
| 405 | exclude: /@babel(?:\/|\\{1,2})runtime/, |
||
| 406 | loader: require.resolve('babel-loader'), |
||
| 407 | options: { |
||
| 408 | babelrc: false, |
||
| 409 | configFile: false, |
||
| 410 | compact: false, |
||
| 411 | presets: [ |
||
| 412 | [ |
||
| 413 | require.resolve('babel-preset-react-app/dependencies'), |
||
| 414 | { helpers: true }, |
||
| 415 | ], |
||
| 416 | ], |
||
| 417 | cacheDirectory: true, |
||
| 418 | cacheCompression: isEnvProduction, |
||
| 419 | |||
| 420 | // If an error happens in a package, it's possible to be |
||
| 421 | // because it was compiled. Thus, we don't want the browser |
||
| 422 | // debugger to show the original code. Instead, the code |
||
| 423 | // being evaluated would be much more helpful. |
||
| 424 | sourceMaps: false, |
||
| 425 | }, |
||
| 426 | }, |
||
| 427 | |||
| 428 | // "postcss" loader applies autoprefixer to our CSS. |
||
| 429 | // "css" loader resolves paths in CSS and adds assets as dependencies. |
||
| 430 | // "style" loader turns CSS into JS modules that inject <style> tags. |
||
| 431 | // In production, we use MiniCSSExtractPlugin to extract that CSS |
||
| 432 | // to a file, but in development "style" loader enables hot editing |
||
| 433 | // of CSS. |
||
| 434 | // By default we support CSS Modules with the extension .module.css |
||
| 435 | { |
||
| 436 | test: cssRegex, |
||
| 437 | exclude: cssModuleRegex, |
||
| 438 | use: getStyleLoaders({ |
||
| 439 | importLoaders: 1, |
||
| 440 | sourceMap: isEnvProduction && shouldUseSourceMap, |
||
| 441 | }), |
||
| 442 | |||
| 443 | // Don't consider CSS imports dead code even if the |
||
| 444 | // containing package claims to have no side effects. |
||
| 445 | // Remove this when webpack adds a warning or an error for this. |
||
| 446 | // See https://github.com/webpack/webpack/issues/6571 |
||
| 447 | sideEffects: true, |
||
| 448 | }, |
||
| 449 | |||
| 450 | // Adds support for CSS Modules (https://github.com/css-modules/css-modules) |
||
| 451 | // using the extension .module.css |
||
| 452 | { |
||
| 453 | test: cssModuleRegex, |
||
| 454 | use: getStyleLoaders({ |
||
| 455 | importLoaders: 1, |
||
| 456 | sourceMap: isEnvProduction && shouldUseSourceMap, |
||
| 457 | modules: true, |
||
| 458 | getLocalIdent: getCSSModuleLocalIdent, |
||
| 459 | }), |
||
| 460 | }, |
||
| 461 | |||
| 462 | // Opt-in support for SASS (using .scss or .sass extensions). |
||
| 463 | // By default we support SASS Modules with the |
||
| 464 | // extensions .module.scss or .module.sass |
||
| 465 | { |
||
| 466 | test: sassRegex, |
||
| 467 | exclude: sassModuleRegex, |
||
| 468 | use: getStyleLoaders( |
||
| 469 | { |
||
| 470 | importLoaders: 2, |
||
| 471 | sourceMap: isEnvProduction && shouldUseSourceMap, |
||
| 472 | }, |
||
| 473 | 'sass-loader' |
||
| 474 | ), |
||
| 475 | |||
| 476 | // Don't consider CSS imports dead code even if the |
||
| 477 | // containing package claims to have no side effects. |
||
| 478 | // Remove this when webpack adds a warning or an error for this. |
||
| 479 | // See https://github.com/webpack/webpack/issues/6571 |
||
| 480 | sideEffects: true, |
||
| 481 | }, |
||
| 482 | |||
| 483 | // Adds support for CSS Modules, but using SASS |
||
| 484 | // using the extension .module.scss or .module.sass |
||
| 485 | { |
||
| 486 | test: sassModuleRegex, |
||
| 487 | use: getStyleLoaders( |
||
| 488 | { |
||
| 489 | importLoaders: 2, |
||
| 490 | sourceMap: isEnvProduction && shouldUseSourceMap, |
||
| 491 | modules: true, |
||
| 492 | getLocalIdent: getCSSModuleLocalIdent, |
||
| 493 | }, |
||
| 494 | 'sass-loader' |
||
| 495 | ), |
||
| 496 | }, |
||
| 497 | |||
| 498 | // "file" loader makes sure those assets get served by WebpackDevServer. |
||
| 499 | // When you `import` an asset, you get its (virtual) filename. |
||
| 500 | // In production, they would get copied to the `build` folder. |
||
| 501 | // This loader doesn't use a "test" so it will catch all modules |
||
| 502 | // that fall through the other loaders. |
||
| 503 | { |
||
| 504 | loader: require.resolve('file-loader'), |
||
| 505 | |||
| 506 | // Exclude `js` files to keep "css" loader working as it injects |
||
| 507 | // its runtime that would otherwise be processed through "file" loader. |
||
| 508 | // Also exclude `html` and `json` extensions so they get processed |
||
| 509 | // by webpacks internal loaders. |
||
| 510 | exclude: [ /\.(js|mjs|jsx|ts|tsx)$/, /\.html$/, /\.json$/ ], |
||
| 511 | options: { |
||
| 512 | name: 'static/media/[name].[hash:8].[ext]', |
||
| 513 | }, |
||
| 514 | }, |
||
| 515 | |||
| 516 | // ** STOP ** Are you adding a new loader? |
||
| 517 | // Make sure to add the new loader(s) before the "file" loader. |
||
| 518 | ], |
||
| 519 | }, |
||
| 520 | ], |
||
| 521 | }, |
||
| 522 | plugins: [ |
||
| 523 | |||
| 524 | // Generates an `index.html` file with the <script> injected. |
||
| 525 | new HtmlWebpackPlugin( |
||
| 526 | Object.assign( |
||
| 527 | {}, |
||
| 528 | { |
||
| 529 | inject: true, |
||
| 530 | template: paths.appHtml, |
||
| 531 | }, |
||
| 532 | isEnvProduction |
||
| 533 | ? { |
||
| 534 | minify: { |
||
| 535 | removeComments: true, |
||
| 536 | collapseWhitespace: true, |
||
| 537 | removeRedundantAttributes: true, |
||
| 538 | useShortDoctype: true, |
||
| 539 | removeEmptyAttributes: true, |
||
| 540 | removeStyleLinkTypeAttributes: true, |
||
| 541 | keepClosingSlash: true, |
||
| 542 | minifyJS: true, |
||
| 543 | minifyCSS: true, |
||
| 544 | minifyURLs: true, |
||
| 545 | }, |
||
| 546 | } |
||
| 547 | : undefined |
||
| 548 | ) |
||
| 549 | ), |
||
| 550 | |||
| 551 | // Inlines the webpack runtime script. This script is too small to warrant |
||
| 552 | // a network request. |
||
| 553 | isEnvProduction && |
||
| 554 | shouldInlineRuntimeChunk && |
||
| 555 | new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [ /runtime~.+[.]js/ ]), |
||
| 556 | |||
| 557 | // Makes some environment variables available in index.html. |
||
| 558 | // The public URL is available as %PUBLIC_URL% in index.html, e.g.: |
||
| 559 | // <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico"> |
||
| 560 | // In production, it will be an empty string unless you specify "homepage" |
||
| 561 | // in `package.json`, in which case it will be the pathname of that URL. |
||
| 562 | // In development, this will be an empty string. |
||
| 563 | new InterpolateHtmlPlugin(HtmlWebpackPlugin, env.raw), |
||
| 564 | |||
| 565 | // This gives some necessary context to module not found errors, such as |
||
| 566 | // the requesting resource. |
||
| 567 | new ModuleNotFoundPlugin(paths.appPath), |
||
| 568 | |||
| 569 | // Makes some environment variables available to the JS code, for example: |
||
| 570 | // if (process.env.NODE_ENV === 'production') { ... }. See `./env.js`. |
||
| 571 | // It is absolutely essential that NODE_ENV is set to production |
||
| 572 | // during a production build. |
||
| 573 | // Otherwise React will be compiled in the very slow development mode. |
||
| 574 | new webpack.DefinePlugin(env.stringified), |
||
| 575 | |||
| 576 | // This is necessary to emit hot updates (currently CSS only): |
||
| 577 | isEnvDevelopment && new webpack.HotModuleReplacementPlugin(), |
||
| 578 | |||
| 579 | // Watcher doesn't work well if you mistype casing in a path so we use |
||
| 580 | // a plugin that prints an error when you attempt to do this. |
||
| 581 | // See https://github.com/facebook/create-react-app/issues/240 |
||
| 582 | isEnvDevelopment && new CaseSensitivePathsPlugin(), |
||
| 583 | |||
| 584 | // If you require a missing module and then `npm install` it, you still have |
||
| 585 | // to restart the development server for Webpack to discover it. This plugin |
||
| 586 | // makes the discovery automatic so you don't have to restart. |
||
| 587 | // See https://github.com/facebook/create-react-app/issues/186 |
||
| 588 | isEnvDevelopment && |
||
| 589 | new WatchMissingNodeModulesPlugin(paths.appNodeModules), |
||
| 590 | isEnvProduction && |
||
| 591 | new MiniCssExtractPlugin({ |
||
| 592 | |||
| 593 | // Options similar to the same options in webpackOptions.output |
||
| 594 | // both options are optional |
||
| 595 | filename: 'static/css/[name].[contenthash:8].css', |
||
| 596 | chunkFilename: 'static/css/[name].[contenthash:8].chunk.css', |
||
| 597 | }), |
||
| 598 | |||
| 599 | // Generate a manifest file which contains a mapping of all asset filenames |
||
| 600 | // to their corresponding output file so that tools can pick it up without |
||
| 601 | // having to parse `index.html`. |
||
| 602 | new ManifestPlugin({ |
||
| 603 | fileName: 'asset-manifest.json', |
||
| 604 | publicPath, |
||
| 605 | }), |
||
| 606 | |||
| 607 | // Moment.js is an extremely popular library that bundles large locale files |
||
| 608 | // by default due to how Webpack interprets its code. This is a practical |
||
| 609 | // solution that requires the user to opt into importing specific locales. |
||
| 610 | // https://github.com/jmblog/how-to-optimize-momentjs-with-webpack |
||
| 611 | // You can remove this if you don't use Moment.js: |
||
| 612 | new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/), |
||
| 613 | |||
| 614 | // Generate a service worker script that will precache, and keep up to date, |
||
| 615 | // the HTML & assets that are part of the Webpack build. |
||
| 616 | isEnvProduction && |
||
| 617 | new WorkboxWebpackPlugin.GenerateSW({ |
||
| 618 | clientsClaim: true, |
||
| 619 | exclude: [ /\.map$/, /asset-manifest\.json$/ ], |
||
| 620 | importWorkboxFrom: 'cdn', |
||
| 621 | navigateFallback: `${publicUrl}/index.html`, |
||
| 622 | navigateFallbackBlacklist: [ |
||
| 623 | |||
| 624 | // Exclude URLs starting with /_, as they're likely an API call |
||
| 625 | new RegExp('^/_'), |
||
| 626 | |||
| 627 | // Exclude URLs containing a dot, as they're likely a resource in |
||
| 628 | // public/ and not a SPA route |
||
| 629 | new RegExp('/[^/]+\\.[^/]+$'), |
||
| 630 | ], |
||
| 631 | }), |
||
| 632 | |||
| 633 | // TypeScript type checking |
||
| 634 | useTypeScript && |
||
| 635 | new ForkTsCheckerWebpackPlugin({ |
||
| 636 | typescript: resolve.sync('typescript', { |
||
| 637 | basedir: paths.appNodeModules, |
||
| 638 | }), |
||
| 639 | async: false, |
||
| 640 | checkSyntacticErrors: true, |
||
| 641 | tsconfig: paths.appTsConfig, |
||
| 642 | compilerOptions: { |
||
| 643 | module: 'esnext', |
||
| 644 | moduleResolution: 'node', |
||
| 645 | resolveJsonModule: true, |
||
| 646 | isolatedModules: true, |
||
| 647 | noEmit: true, |
||
| 648 | jsx: 'preserve', |
||
| 649 | }, |
||
| 650 | reportFiles: [ |
||
| 651 | '**', |
||
| 652 | '!**/*.json', |
||
| 653 | '!**/__tests__/**', |
||
| 654 | '!**/?(*.)(spec|test).*', |
||
| 655 | '!**/src/setupProxy.*', |
||
| 656 | '!**/src/setupTests.*', |
||
| 657 | ], |
||
| 658 | watch: paths.appSrc, |
||
| 659 | silent: true, |
||
| 660 | formatter: typescriptFormatter, |
||
| 661 | }), |
||
| 662 | ].filter(Boolean), |
||
| 663 | |||
| 664 | // Some libraries import Node modules but don't use them in the browser. |
||
| 665 | // Tell Webpack to provide empty mocks for them so importing them works. |
||
| 666 | node: { |
||
| 667 | dgram: 'empty', |
||
| 668 | fs: 'empty', |
||
| 669 | net: 'empty', |
||
| 670 | tls: 'empty', |
||
| 671 | child_process: 'empty', |
||
| 672 | }, |
||
| 673 | |||
| 674 | // Turn off performance processing because we utilize |
||
| 675 | // our own hints via the FileSizeReporter |
||
| 676 | performance: false, |
||
| 677 | }; |
||
| 678 | }; |
||
| 679 |